package com.liu.netty.demo.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.util.Timer;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

/**
 * @program: https://www.joinsunsoft.com
 * @description:
 * @author: LiuYong
 * @email: david.liu@ginghan.com
 * @create: 2022/3/23 10:58
 */

@Slf4j
public class ConnectionWatchdog<T> extends ChannelHandlerAdapter implements Runnable{
    private final Bootstrap bootstrap;
    private final DemoClient.ClientConnectionInfo worker;
    private int maxRetry = 20;
    private int interval = 60;
    private TimeUnit timeUnit;

    private Channel channel;

    public ConnectionWatchdog(Bootstrap bootstrap, DemoClient.ClientConnectionInfo work, int maxRetry, int interval){
        this(bootstrap, work, maxRetry, interval, TimeUnit.SECONDS);
    }

    public ConnectionWatchdog(Bootstrap bootstrap, DemoClient.ClientConnectionInfo work, int maxRetry, int interval, TimeUnit timeUnit) {
        this.bootstrap = bootstrap;
        this.maxRetry = maxRetry;
        this.interval = interval;
        this.timeUnit = timeUnit;
        this.worker = work;
    }

    /**
     * channel链路每次active的时候，将其连接的次数重新☞ 0
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("-------客户端上线----------");
        log.info("当前链路已经激活了，重连尝试次数重新置为0");
        worker.resetAttempts();
        InetSocketAddress address = (InetSocketAddress) (ctx.channel().localAddress());
        log.error("================== {} connect now ", address);
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("-------客户端下线----------");
        worker.add();

        boolean isChannelActive = true;
        if(null == channel || !channel.isActive()){
            isChannelActive = false;
        }else{
            try{
                channel.close();
            }catch (Exception e){
                log.error("close active channel error", e);
            }
        }

        if (worker.getAttempts() < maxRetry) {
            log.info("链接已经关闭，将在{}{}后进行第{}次重连", interval+"", timeUnit, worker.getAttempts()+"");
            ctx.executor().schedule(this, interval, timeUnit);
            //ctx.channel().eventLoop().execute(this);
            //ctx.executor().schedule(this, timeout, TimeUnit.SECONDS);
        }else{
            log.info("重连已经超过最大次数{},将退出重连", maxRetry+"");
            try{
                ctx.fireExceptionCaught(new IllegalArgumentException("重连已经超过最大次数"));
                worker.getWork().shutdownGracefully();
            }catch (Exception e){
                log.error("close active channel error", e);
            }
        }


//        if(isChannelActive == false){
//            log.info("链接关闭，将进行重连");
//
//            if (attempts < maxRetry) {
//                ctx.executor().schedule(this, interval, timeUnit);
//                //ctx.channel().eventLoop().execute(this);
//                //ctx.executor().schedule(this, timeout, TimeUnit.SECONDS);
//            }else{
//                ctx.disconnect();
//                log.info("链接关闭");
//            }
//        }
//        else
//        {
//        }
    }

    public void run() {
        ChannelFuture future;
        //bootstrap已经初始化好了，只需要将handler填入就可以了
        future = bootstrap.connect();

        //future对象监听
        future.addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture f) throws Exception {
                boolean succeed = f.isSuccess();
                Channel channel=f.channel();
                if (!succeed) {
                    log.info("重连失败");
                    f.channel().pipeline().fireChannelInactive();
                }else{
                    worker.resetAttempts();
                    log.info("重连成功");
                }
            }
        });
    }
}
